<template>
  <div class="editor-container">
    <!-- 左侧模型列表 -->
    <div class="model-sidebar">
      <div class="sidebar-title">模型库</div>
      <div v-for="group in modelGroups" :key="group.name" class="model-group">
        <div class="group-header" @click="group.expanded = !group.expanded">
          <i :class="['arrow', group.expanded ? 'down' : 'right']"></i>
          {{ group.name }}
        </div>
        <div v-show="group.expanded" class="group-content">
          <div v-for="model in group.models" :key="model.name" class="model-item" @click="addModelToCenter(model)">
            <img :src="model.preview" :alt="model.name">
            <span>{{ model.name }}</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 中间场景编辑区 -->
    <div class="scene-container" ref="container">
      <!-- 添加标签容器 -->
      <div v-if="showLabels" class="label-container">
        <div v-for="(label, index) in modelLabels" :key="index" :style="label.style" class="model-label"
          v-show="label.visible">
          <div class="label-header">
            <span class="label-title">{{ label.title }}</span>
            <label class="switch">
              <input type="checkbox" v-model="label.switchState" @change="handleSwitchChange(label)">
              <span class="slider"></span>
            </label>
          </div>
          <div class="label-content">
            <div v-if="label.object.userData.customFields">
              <div v-for="(value, key) in label.object.userData.customFields" :key="key" class="label-field">
                <span>{{ key }}: {{ value }}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
      <!-- 工具栏 -->
      <div ref="toolbar" class="toolbar">
        <button @click="setMode('translate')">移动</button>
        <button @click="setMode('rotate')">旋转</button>
        <button @click="setMode('scale')">缩放</button>
        <button @click="showLabels = !showLabels">显示标签{{ modelLabels.length }}</button>
        <button @click="handleSaveScene">保存场景</button>
        <input type="file" accept=".json" style="display: none" ref="fileInput" @change="handleLoadScene">
        <button @click="$refs.fileInput.click()">加载场景</button>
      </div>
    </div>

    <!-- 右侧属性面板 -->
    <div class="property-panel" v-if="selectedObject">
      <div class="panel-header">
        <h2>属性设置</h2>
        <!-- 添加删除按钮 -->
        <button class="delete-btn" @click="deleteSelectedObject">
          删除模型
        </button>
      </div>

      <div class="tabs">
        <div v-for="(item, index) in tabs" :key="item" :class="{ active: index == tabIndex }" class="tabs-item"
          @click="tabIndex = index">{{ item }}</div>
      </div>
      <div v-if="tabIndex==0">
        <h3 class="">属性编辑</h3>
        <div class="property-content">
          <!-- 添加名称设置 -->
          <div class="property-group">
            <div class="property-row">
              <label class="label">模型名称:</label>
              <input type="text" v-model="objectProps.name" @change="updateObjectName($event.target.value)"
                placeholder="请输入模型名称">
            </div>
          </div>
          <div class="property-group">
            <div class="property-row">
              <label class="label">显示标签:</label>
              <label class="switch">
                <input type="checkbox" v-model="objectProps.showLabel" @change="updateShowLabel(objectProps.showLabel)">
                <span class="slider"></span>
              </label>
            </div>
          </div>
          <div class="property-group">
            <h3>位置</h3>
            <div class="property-row">
              <label class="label">X:</label>
              <input type="number" v-model.number="objectProps.position.x" @input="updatePosition">
            </div>
            <div class="property-row">
              <label class="label">Y:</label>
              <input type="number" v-model.number="objectProps.position.y" @input="updatePosition">
            </div>
            <div class="property-row">
              <label class="label">Z:</label>
              <input type="number" v-model.number="objectProps.position.z" @input="updatePosition">
            </div>
          </div>
          <div class="property-group">
            <h3>旋转</h3>
            <div class="property-row">
              <label class="label">X:</label>
              <input type="number" v-model.number="objectProps.rotation.x" @input="updateRotation" step="0.1">
            </div>
            <div class="property-row">
              <label class="label">Y:</label>
              <input type="number" v-model.number="objectProps.rotation.y" @input="updateRotation" step="0.1">
            </div>
            <div class="property-row">
              <label class="label">Z:</label>
              <input type="number" v-model.number="objectProps.rotation.z" @input="updateRotation" step="0.1">
            </div>
          </div>
          <h3>缩放</h3> <!-- 新增缩放部分 -->
          <div class="property-row">
            <label class="label">X:</label>
            <input type="number" v-model.number="objectProps.scale.x" @input="updateScale">
          </div>
          <div class="property-row">
            <label class="label">Y:</label>
            <input type="number" v-model.number="objectProps.scale.y" @input="updateScale">
          </div>
          <div class="property-row">
            <label class="label">Z:</label>
            <input type="number" v-model.number="objectProps.scale.z" @input="updateScale">
          </div>
          <div class="property-group">
            <h3>颜色</h3>
            <input type="color" v-model="objectProps.color" @input="updateColor">
          </div>
          <!-- 连接管道特有的属性 -->
          <div class="property-group" v-if="selectedObject?.userData?.tubeConfig">
            <h3>管道设置</h3>

            <div class="property-row">
              <label class="label">流动贴图:</label>
              <label class="switch">
                <input type="checkbox" v-model="objectProps.tubeConfig.useTexture"
                  @change="updateTubeConfig({ useTexture: $event.target.checked })">
                <span class="slider"></span>
              </label>
            </div>

            <template v-if="objectProps.tubeConfig.useTexture">
              <div class="property-row">
                <label class="label">流动方向:</label>
                <select v-model.number="objectProps.tubeConfig.direction"
                  @change="updateTubeConfig({ direction: $event.target.value })">
                  <option :value="1">正向</option>
                  <option :value="-1">反向</option>
                </select>
              </div>

              <div class="property-row">
                <label class="label">流动速度:</label>
                <input type="number" v-model.number="objectProps.tubeConfig.flowSpeed"
                  @input="updateTubeConfig({ flowSpeed: $event.target.value })" step="0.01">
              </div>
            </template>

            <div class="property-row">
              <label class="label">管道半径:</label>
              <input type="number" v-model.number="objectProps.tubeConfig.radius"
                @input="updateTubeConfig({ radius: $event.target.value })" step="0.01">
            </div>

            <div class="property-row">
              <label class="label">透明度:</label>
              <input type="number" v-model.number="objectProps.tubeConfig.opacity"
                @input="updateTubeConfig({ opacity: $event.target.value })" step="0.1" min="0" max="1">
            </div>

            <div class="property-row">
              <label class="label">颜色:</label>
              <input type="color" v-model="objectProps.tubeConfig.color" @input="updateTubeConfig({
                color: parseInt($event.target.value.replace('#', ''), 16)
              })">
            </div>
            <!-- 添加路径编辑部分 -->
            <div class="path-editor">
              <div class="path-header">
                <h4>路径点</h4>
                <button @click="addPathPoint" class="add-point-btn">添加路径点</button>
              </div>
              <div class="path-points">
                <div v-for="(point, index) in objectProps.tubeConfig.points" :key="index" class="path-point">
                  <div class="point-header">
                    <span>点 {{ index + 1 }}</span>
                    <button @click="removePathPoint(index)" class="remove-point-btn"
                      :disabled="objectProps.tubeConfig.points.length <= 2">
                      删除
                    </button>
                  </div>
                  <div class="point-coords">
                    <div class="coord-input">
                      <label class="label">X:</label>
                      <input type="number" v-model.number="point.x" @input="updateTubePath" step="0.1">
                    </div>
                    <div class="coord-input">
                      <label class="label">Y:</label>
                      <input type="number" v-model.number="point.y" @input="updateTubePath" step="0.1">
                    </div>
                    <div class="coord-input">
                      <label class="label">Z:</label>
                      <input type="number" v-model.number="point.z" @input="updateTubePath" step="0.1">
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <!-- 添加自定义字段组 -->
          <div class="property-group">
            <div class="custom-fields-header">
              <h3>自定义字段</h3>
              <button @click="addCustomField" class="add-field-btn">添加字段</button>
            </div>
            <div v-for="(value, key) in objectProps.customFields" :key="key" class="custom-field-row">
              <input type="text" :value="customFieldKeys[key]" class="field-key" placeholder="字段名"
                @input="handleFieldKeyInput($event, key)" @blur="handleFieldKeyBlur(key)" @focus="handleInputFocus">
              <input type="text" v-model="objectProps.customFields[key]" class="field-value" placeholder="字段值"
                @input="updateCustomField(key, $event.target.value)" @focus="handleInputFocus" @blur="handleInputBlur">
              <button @click="removeCustomField(key)" class="remove-field-btn" @mouseenter="handleInputFocus"
                @mouseleave="handleInputBlur">删除</button>
            </div>
          </div>
        </div>
      </div>
      <div v-if="tabIndex==1">
        <div class="property-content">
          <div class="property-group">
            <h3>基础信息</h3>
            <div class="property-row">
              <label class="label">模型名称:</label>
              <input type="text" v-model="objectProps.name" @change="updateObjectName($event.target.value)"
                placeholder="请输入模型名称">
            </div>
            <div class="property-row">
              <label class="label">模型编号:</label>
              <input type="text"
                placeholder="请输入模型编号">
            </div>
          </div>
          <div class="property-group">
            <h3>DTU信息</h3>
            <div class="property-row">
              <label class="label">DTU IMEI:</label>
              <input type="text"
                placeholder="请输入内容">
            </div>
          </div>
          <div class="property-group">
            <h3>关联设备</h3>
            <div class="property-row">
              <label class="label">外设:</label>
              <input type="text"
                placeholder="请输入内容">
            </div>
            <div class="property-row">
              <label class="label">传感:</label>
              <div>
                123
              </div>
            </div>
          </div>
        </div>
      </div>
      <div v-if="tabIndex==1">
        <div class="property-content">
          <div class="property-group">
            <h3>基础信息</h3>
            <div class="property-row">
              <label class="label">模型名称:</label>
              <input type="text" v-model="objectProps.name" @change="updateObjectName($event.target.value)"
                placeholder="请输入模型名称">
            </div>
            <div class="property-row">
              <label class="label">模型编号:</label>
              <input type="text"
                placeholder="请输入模型编号">
            </div>
          </div>
          <div class="property-group">
            <h3>DTU信息</h3>
            <div class="property-row">
              <label class="label">DTU IMEI:</label>
              <input type="text"
                placeholder="请输入内容">
            </div>
          </div>
          <div class="property-group">
            <h3>关联设备</h3>
            <div class="property-row">
              <label class="label">外设:</label>
              <input type="text"
                placeholder="请输入内容">
            </div>
            <div class="property-row">
              <label class="label">传感:</label>
              <div>
                123
              </div>
            </div>
          </div>
        </div>
      </div>
      <div v-if="tabIndex==2">
        <div class="property-content">
          <div class="property-group">
            <h3>启停状态</h3>
            <div class="property-row">
              <label class="label">PLC地址:</label>
              <input type="text" v-model="objectProps.name" @change="updateObjectName($event.target.value)"
                placeholder="请输入内容">
            </div>
            <div class="property-row">
              <label class="label">PLC从站:</label>
              <input type="text"
                placeholder="请输入内容">
            </div>
            <div class="property-row">
              <label class="label">是否显示:</label>
              <label class="switch">
                <input type="checkbox">
                <span class="slider"></span>
              </label>
            </div>
            <div class="property-row">
              <label class="label">是否可写:</label>
              <label class="switch">
                <input type="checkbox">
                <span class="slider"></span>
              </label>
            </div>
            <div class="property-row">
              <label class="label">类型:</label>
              <div>
                <input type="radio" id="male" name="gender" value="male" checked>
                <label for="male">开关类</label>
                <input type="radio" id="female" name="gender" value="female">
                <label for="female">参数类</label>
              </div>
              
            </div>
          </div>
          <button>新增属性</button>
        </div>
      </div>
      <div v-if="tabIndex==3">
        <div class="property-content">
          <div class="property-group">
            <h3>启停状态</h3>
            <div class="property-row">
              <label class="label">PLC地址:</label>
              <input type="text" v-model="objectProps.name" @change="updateObjectName($event.target.value)"
                placeholder="请输入内容">
            </div>
            <div class="property-row">
              <label class="label">PLC从站:</label>
              <input type="text"
                placeholder="请输入内容">
            </div>
            <div class="property-row">
              <label class="label">是否显示:</label>
              <label class="switch">
                <input type="checkbox">
                <span class="slider"></span>
              </label>
            </div>
            <div class="property-row">
              <label class="label">是否可写:</label>
              <label class="switch">
                <input type="checkbox">
                <span class="slider"></span>
              </label>
            </div>
            <div class="property-row">
              <label class="label">常开状态:</label>
            </div>
            <div class="property-row">
              <label class="label">闭合状态:</label>
            </div>
            <div class="property-row">
              <label class="label">类型:</label>
              <div>
                <input type="radio" id="male" name="gender" value="male" checked>
                <label for="male">开关类</label>
                <input type="radio" id="female" name="gender" value="female">
                <label for="female">参数类</label>
              </div>
              
            </div>
          </div>
          <button>新增属性</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import * as THREE from 'three';
import {
  OrbitControls
} from 'three/examples/jsm/controls/OrbitControls';
import {
  TransformControls
} from 'three/examples/jsm/controls/TransformControls';
// 导入hdr加载器
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";

// 后处理扩展库
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
// 引入渲染器通道RenderPass
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
// 引入OutlinePass通道
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js';

import * as TWEEN from "three/examples/jsm/libs/tween.module.js";

// 实例化加载器gltf
const gltfLoader = new GLTFLoader();

export default {
  name: 'SceneEditor',

  data() {
    return {
      is2DMode: false, // 新增状态，跟踪当前场景模式
      scene: null,
      camera: null,
      renderer: null,
      controls: null,
      transformControls: null,
      renderPass: null,
      outlinePass: null,
      composer: null,
      selectedObject: null,
      objectProps: {
        position: {
          x: 0,
          y: 0,
          z: 0
        },
        rotation: {
          x: 0,
          y: 0,
          z: 0
        },
        scale: {
          x: 1,
          y: 1,
          z: 1
        },
        color: '#808080',
        tubeConfig: {      // 添加管道配置
          flowSpeed: 0.02,
          direction: 1,
          radius: 0.1,
          opacity: 0.8,
          color: '#47d8fa',
          useTexture: true, // 添加贴图开关属性
          points: []
        },
        customFields: {},  // 添加自定义字段对象
      },
      customFieldKeys: {}, // 用于跟踪字段名的临时存储
      modelGroups: [{
        name: '基础图形',
        expanded: true,
        models: [{
          name: '立方体',
          type: 'cube',
          preview: '',
          showLabel: true,
          create: () => new THREE.BoxGeometry(1, 1, 1)
        },
        {
          name: '球体',
          type: 'sphere',
          preview: '',
          showLabel: true,
          create: () => new THREE.SphereGeometry(0.5, 32, 32)
        }, {
          name: '管道',
          type: 'tube',
          preview: '',
          showLabel: false,
          create: () => ({
            type: 'tube',
            points: [
              new THREE.Vector3(0, 0.1, 0),
              new THREE.Vector3(0, 0.1, 2)
            ],
            config: {
              radius: 0.1,
              segments: 64,
              radialSegments: 8,
              flowSpeed: 0.02,
              direction: 1,
              color: 0x47d8fa,
              opacity: 0.8
            }
          })
        }]
      },
      {
        name: 'GLB模型',
        expanded: true,
        models: [{
          name: '模型123',
          type: 'glb',
          showLabel: true,
          preview: '/previews/model1.png', // 预览图路径
          path: './model/123.glb' // GLB文件路径
        },
        {
          name: '模型1232',
          type: 'glb',
          showLabel: true,
          preview: '/previews/model1.png', // 预览图路径
          path: './model/1232.glb' // GLB文件路径
        },
        {
          name: '模型水池',
          type: 'glb',
          showLabel: true,
          preview: '/previews/model1.png', // 预览图路径
          path: './model/水池.glb' // GLB文件路径
        },
        {
          name: '模型水池2',
          type: 'glb',
          showLabel: true,
          preview: '/previews/model1.png', // 预览图路径
          path: './model/水池2.glb' // GLB文件路径
        },
        ]
      }],
      currentDragModel: null,
      diyGroup: null,
      sceneData: {
        name: '未命名场景',
        version: '1.0',
        models: []
      },

      tubeConfig: {
        radius: 0.05,
        segments: 64,
        radialSegments: 8,
        flowSpeed: 0.02,
        direction: 1,
        color: 0x47d8fa,
        opacity: 0.8
      },
      modelLabels: [], // 用于存储标签数据
      showLabels: false, // 添加标签显示控制
      tabs: ['属性设置', '设备关联', '字设置', '位设置'],
      tabIndex: 0,
    }
  },

  mounted() {
    this.$nextTick(() => {
      this.initThreeJS();
      // this.initToolbar(); // 初始化工具栏
      this.animate();
      this.preloadModels()
    });
  },

  methods: {
    // 切换场景模式的方法
    toggleSceneMode() {
      this.is2DMode = !this.is2DMode; // 切换模式
      this.updateCameraForMode(); // 更新相机设置
    },

    // 更新相机设置以适应当前模式
    updateCameraForMode() {
      if (this.is2DMode) {
        // 设置为2D模式
        this.camera.position.set(0, 1000, 0); // 适当调整相机位置
        this.camera.lookAt(0, 0, 0); // 观察中心
        this.camera.fov = 1; // 设置视场角
        this.camera.updateProjectionMatrix(); // 更新投影矩阵
        // this.controls.enabled = false
      } else {
        // 设置为3D模式
        this.camera.position.set(2, 10, 10); // 恢复3D模式的相机位置
        this.camera.lookAt(0, 0, 0); // 观察中心
        this.camera.fov = 75; // 恢复视场角
        this.camera.updateProjectionMatrix(); // 更新投影矩阵
        this.controls.enabled = true
      }

    },
    // 在工具栏中添加切换按钮
    initToolbar() {
      // ... existing toolbar initialization ...
      const toggleButton = document.createElement('button');
      toggleButton.textContent = '切换场景模式';
      toggleButton.onclick = this.toggleSceneMode; // 绑定切换方法
      this.$refs.toolbar.appendChild(toggleButton); // 将按钮添加到工具栏
    },
    initThreeJS() {
      // 创建场景
      this.scene = new THREE.Scene();
      this.scene.background = new THREE.Color(0xf0f0f0);

      // 创建相机
      this.camera = new THREE.PerspectiveCamera(
        75,
        this.$refs.container.clientWidth / this.$refs.container.clientHeight,
        0.1,
        10000
      );
      this.camera.position.set(-2, 10, 10);
      this.camera.lookAt(0, 0, 0);

      // 创建渲染器
      this.renderer = new THREE.WebGLRenderer({
        antialias: true
      });
      this.renderer.setSize(
        this.$refs.container.clientWidth,
        this.$refs.container.clientHeight
      );
      this.$refs.container.appendChild(this.renderer.domElement);

      // 创建控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      // 设置旋转
      // this.controls.autoRotate = true;
      // 创建变换控制器
      this.transformControls = new TransformControls(this.camera, this.renderer.domElement);
      this.scene.add(this.transformControls.getHelper());

      // 添加 TransformControls 事件监听
      this.transformControls.addEventListener('dragging-changed', (event) => {
        this.controls.enabled = !event.value;
      });

      // 添加 change 事件监听，确保在变换后更新
      this.transformControls.addEventListener('change', () => {
        if (this.selectedObject) {
          // 更新旋转数据
          this.objectProps.rotation = {
            x: THREE.MathUtils.radToDeg(this.selectedObject.rotation.x),
            y: THREE.MathUtils.radToDeg(this.selectedObject.rotation.y),
            z: THREE.MathUtils.radToDeg(this.selectedObject.rotation.z)
          };
          this.objectProps.position = {
            x: this.selectedObject.position.x,
            y: this.selectedObject.position.y,
            z: this.selectedObject.position.z
          };
          this.objectProps.scale = {
            x: this.selectedObject.scale.x,
            y: this.selectedObject.scale.y,
            z: this.selectedObject.scale.z
          };
        }
      });

      // 添加点击事件监听
      this.renderer.domElement.addEventListener('click', this.onSceneClick);

      // 添加灯光
      const ambientLight = new THREE.AmbientLight(0xffffff, 1);
      this.scene.add(ambientLight);

      const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
      directionalLight.position.set(10, 10, 10);
      directionalLight.castShadow = true;
      this.scene.add(directionalLight);

      // 启用阴影
      this.renderer.shadowMap.enabled = true;

      // 添加网格
      const gridHelper = new THREE.GridHelper(20, 20);
      this.scene.add(gridHelper);

      // rgbeLoader 加载hdr贴图
      // let rgbeLoader = new RGBELoader();
      // rgbeLoader.load("./texture/Alex_Hart-Nature_Lab_Bones_2k.hdr", (envMap) => {
      //     // 设置球形贴图
      //     envMap.mapping = THREE.EquirectangularRefractionMapping;
      //     // 设置环境贴图
      //     this.scene.background = envMap;

      // });
      var cubeLoader = new THREE.CubeTextureLoader();
      this.scene.background = cubeLoader.load([
        './texture/dusk/posx.jpg',
        './texture/dusk/negx.jpg',
        './texture/dusk/posy.jpg',
        './texture/dusk/negy.jpg',
        './texture/dusk/posz.jpg',
        './texture/dusk/negz.jpg'
      ])

      // 创建后处理对象EffectComposer，WebGL渲染器作为参数
      this.composer = new EffectComposer(this.renderer);
      // 创建一个渲染器通道，场景和相机作为参数
      this.renderPass = new RenderPass(this.scene, this.camera);
      // 设置renderPass通道
      this.composer.addPass(this.renderPass);
      // OutlinePass第一个参数v2的尺寸和canvas画布保持一致
      const v2 = new THREE.Vector2(this.$refs.container.clientWidth, this.$refs.container.clientHeight);
      // const v2 = new THREE.Vector2(800, 600);
      this.outlinePass = new OutlinePass(v2, this.scene, this.camera);
      this.outlinePass.pulsePeriod = 2;
      // 设置OutlinePass通道
      this.composer.addPass(this.outlinePass);



      // 监听窗口大小变化
      window.addEventListener('resize', this.onWindowResize);


      // 创建 DIY 模型组
      this.diyGroup = new THREE.Group();
      this.diyGroup.name = 'diy-models';
      this.scene.add(this.diyGroup);
    },

    animate() {
      requestAnimationFrame(this.animate);

      // 更新流动效果
      this.diyGroup.traverse((object) => {
        if (object.userData?.tubeConfig) {
          // 计算新的流动偏移
          const speed = object.userData.tubeConfig.flowSpeed || 0.02;
          const direction = object.userData.tubeConfig.direction || 1;

          if (!object.userData.flowOffset) {
            object.userData.flowOffset = 0;
          }

          object.userData.flowOffset += speed * -1;

          // 应用流动效果
          if (object.material?.map) {
            object.material.map.offset.x = object.userData.flowOffset;
            object.material.needsUpdate = true;
          }
        }
      });
      TWEEN.update()
      // this.controls.update();
      this.updateLabelsPosition();
      // this.composer.render();
      this.renderer.render(this.scene, this.camera);
    },

    async addModelToCenter(model) {
      try {
        let mesh
        if (model.type === 'tube') {
          const tubeData = model.create();
          mesh = this.createFlowTube({
            points: tubeData.points,
            ...tubeData.config
          });

          // 保存管道配置到 userData
          mesh.userData.tubeConfig = {
            ...tubeData.config,
            name: model.name,
            points: tubeData.points.map(p => p.clone())
          };
        } else if (model.type === 'glb') {

          // 添加加载提示
          const loadingDiv = document.createElement('div')
          loadingDiv.className = 'loading-tip'
          loadingDiv.textContent = '加载中...'
          this.$refs.container.appendChild(loadingDiv)

          // 加载 GLB 模型
          const gltf = await new Promise((resolve, reject) => {
            gltfLoader.load(
              model.path,
              resolve,
              (progress) => {
                const percent = Math.floor((progress.loaded / progress.total) * 100)
                loadingDiv.textContent = `加载中... ${percent}%`
              },
              reject
            )
          })
          // 移除加载提示
          this.$refs.container.removeChild(loadingDiv)

          mesh = gltf.scene

          // 为整个模型添加 userData
          mesh.userData = {
            ...mesh.userData,
            customFields: {},
            name: model.name,
            modelPath: model.path,
            isGLBModel: true, // 标记为 GLB 模型
          };

          // 调整模型大小和位置
          const box = new THREE.Box3().setFromObject(mesh)
          const size = box.getSize(new THREE.Vector3())
          const maxDim = Math.max(size.x, size.y, size.z)
          const scale = 1 / maxDim // 将最大尺寸缩放到1单位
          mesh.scale.multiplyScalar(scale)

          // 居中模型
          box.setFromObject(mesh)
          const center = box.getCenter(new THREE.Vector3())
          mesh.position.sub(center)
          mesh.position.y = -(0 + box.min.y) // 底部移到地面
        } else {
          // 原有的基础几何体处理
          const geometry = model.create()
          const material = new THREE.MeshStandardMaterial({
            color: 0x808080,
            metalness: 0.1,
            roughness: 0.8
          })
          mesh = new THREE.Mesh(geometry, material)
          mesh.position.set(0, 0.5, 0)
          mesh.userData = {
            ...mesh.userData,
            customFields: {},
            name: model.name,
          };
        }
        mesh.userData.showLabel = model.showLabel

        this.diyGroup.add(mesh)
        this.selectObject(mesh)
        this.renderer.render(this.scene, this.camera)

      } catch (error) {
        console.error('添加模型失败:', error)
      }
    },

    selectObject(object) {
      try {
        // 先分离之前的对象
        if (this.transformControls.object) {
          this.transformControls.detach();
        }
        this.selectedObject = object;

        if (object?.userData?.tubeConfig) {
          // 更新管道配置
          this.objectProps.tubeConfig = {
            ...object.userData.tubeConfig,
            points: object.userData.tubeConfig.points.map(p => p.clone())
          };
        }
        if (object) {
          this.objectProps.showLabel = object.userData.showLabel !== undefined ? object.userData.showLabel : true; // showLabel
          // 更新属性数据
          this.objectProps.position = {
            x: object.position.x,
            y: object.position.y,
            z: object.position.z
          };
          this.objectProps.scale = {
            x: object.scale.x,
            y: object.scale.y,
            z: object.scale.z
          };
          this.objectProps.rotation = {
            x: THREE.MathUtils.radToDeg(object.rotation.x),
            y: THREE.MathUtils.radToDeg(object.rotation.y),
            z: THREE.MathUtils.radToDeg(object.rotation.z)
          };

          if (object.material && object.material.color) {
            this.objectProps.color = '#' + object.material.color.getHexString();
          }
          // 加载自定义字段
          this.objectProps.customFields = {};
          this.customFieldKeys = {};
          // 确保 userData 和 customFields 存在
          if (!object.userData) {
            object.userData = {};
          }
          if (!object.userData.customFields) {
            object.userData.customFields = {};
          }

          // 加载自定义字段
          Object.entries(object.userData.customFields).forEach(([key, value]) => {
            this.$set(this.objectProps.customFields, key, value);
            this.$set(this.customFieldKeys, key, key);
          });

          this.objectProps.name = object.userData.name

          // 附加变换控制器
          this.transformControls.attach(object);

          // 查找或创建标签
          this.getOrCreateLabel(object);
        }
      } catch (error) {
        console.error('选择对象时出错:', error);
      }
    },
    // 新增创建或获取标签的方法
    getOrCreateLabel(object) {
      if (object.userData?.type === 'tube') return;
      let labelIndex = this.modelLabels.findIndex(l => l.object === object);
      if (labelIndex == -1) {
        let label = {
          object: object,
          title: object.userData?.name || '未命名模型',
          style: {},
          visible: true,
          switchState: false
        };
        this.modelLabels.push(label);
      } else {
        this.$set(this.modelLabels[labelIndex], 'title', object.userData?.name || '未命名模型')
      }
    },
    // 更新模型名称
    updateObjectName(newName) {
      if (this.selectedObject) {
        this.selectedObject.userData.name = newName;
      }
    },
    updateShowLabel(value) {
      if (this.selectedObject) {
        this.selectedObject.userData.showLabel = value; // 更新模型的 showLabel 属性
        // 如果关闭标签，删除对应的标签
        if (!value) {
          this.modelLabels = this.modelLabels.filter(label => label.object !== this.selectedObject);
        } else {
          // 如果开启标签，确保标签存在
          this.getOrCreateLabel(this.selectedObject);
        }
      }
    },
    // 更新位置的方法
    updatePosition() {
      if (this.selectedObject) {
        this.selectedObject.position.set(
          this.objectProps.position.x,
          this.objectProps.position.y,
          this.objectProps.position.z
        );
      }
    },
    // 更新旋转的方法
    updateRotation() {
      if (this.selectedObject) {
        this.selectedObject.rotation.set(
          THREE.MathUtils.degToRad(this.objectProps.rotation.x),
          THREE.MathUtils.degToRad(this.objectProps.rotation.y),
          THREE.MathUtils.degToRad(this.objectProps.rotation.z)
        );
      }
    },
    // 新增更新缩放的方法
    updateScale() {
      if (this.selectedObject) {
        this.selectedObject.scale.set(
          this.objectProps.scale.x,
          this.objectProps.scale.y,
          this.objectProps.scale.z
        );
      }
    },
    // 更新颜色的方法
    updateColor() {
      if (this.selectedObject && this.selectedObject.material) {
        this.selectedObject.material.color.setStyle(this.objectProps.color);
      }
    },
    setMode(mode) {
      if (this.transformControls) {
        this.transformControls.setMode(mode);
      }
    },

    onWindowResize() {
      if (this.camera && this.renderer) {
        this.camera.aspect = this.$refs.container.clientWidth / this.$refs.container.clientHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(
          this.$refs.container.clientWidth,
          this.$refs.container.clientHeight
        );
      }
    },
    // 添加场景清理方法
    disposeScene(scene) {
      if (this.diyGroup) {
        this.diyGroup.traverse((object) => {
          if (object.geometry) {
            object.geometry.dispose();
          }
          if (object.material) {
            if (Array.isArray(object.material)) {
              object.material.forEach(material => material.dispose());
            } else {
              object.material.dispose();
            }
          }
        });
      }
      scene.traverse((object) => {
        if (object.geometry) {
          object.geometry.dispose();
        }
        if (object.material) {
          if (Array.isArray(object.material)) {
            object.material.forEach(material => material.dispose());
          } else {
            object.material.dispose();
          }
        }
      });
    },


    // 修改保存场景的方法
    handleSaveScene() {
      try {
        const sceneData = {
          name: 'MyScene',
          version: '1.0',
          models: [],
        };

        // 遍历 diyGroup 的子对象
        this.diyGroup.children.forEach((object) => {
          if (object.userData?.tubeConfig) {
            // 确保有有效的路径点
            const points = object.userData.tubeConfig.points || [];
            if (points.length < 2) {
              console.warn('管道路径点不足，添加默认点');
              points.push(new THREE.Vector3(0, 1, 0));
            }

            const tubeData = {
              uuid: object.uuid,
              type: 'tube',
              position: {
                x: object.position.x,
                y: object.position.y,
                z: object.position.z
              },
              rotation: {
                x: object.rotation.x,
                y: object.rotation.y,
                z: object.rotation.z
              },
              scale: {
                x: object.scale.x,
                y: object.scale.y,
                z: object.scale.z
              },
              tubeConfig: {
                ...object.userData.tubeConfig,
                points: points.map(p => ({
                  x: p.x,
                  y: p.y,
                  z: p.z
                }))
              },
              name: object.userData?.name || '',
              customFields: object.userData?.customFields || {}
            };
            sceneData.models.push(tubeData);
          }
          // 如果是普通模型
          else if (object instanceof THREE.Mesh || object.userData?.isGLBModel) {
            const modelData = {
              uuid: object.uuid,
              type: object.userData?.isGLBModel ? 'glb' : 'mesh',
              modelPath: object.userData?.modelPath,
              position: {
                x: object.position.x,
                y: object.position.y,
                z: object.position.z
              },
              rotation: {
                x: object.rotation.x,
                y: object.rotation.y,
                z: object.rotation.z
              },
              scale: {
                x: object.scale.x,
                y: object.scale.y,
                z: object.scale.z
              },
              name: object.userData?.name || '',
              customFields: object.userData?.customFields || {}
            };

            // 保存材质信息(针对基础几何体)
            if (object.material && !object.userData?.isGLBModel) {
              modelData.material = {
                color: object.material.color.getHexString(),
                opacity: object.material.opacity
              };
            }

            sceneData.models.push(modelData);
          }
        });

        // 保存文件
        const jsonString = JSON.stringify(sceneData, null, 2);
        const blob = new Blob([jsonString], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'scene.json';
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);

      } catch (error) {
        console.error('保存场景失败:', error);
      }
    },

    handleFile() {
      uni.chooseFile({
        count: 1, //默认100
        extension: ['.json'],
        success: (res) => {
          this.handleLoadScene(res.tempFiles[0])
        }
      });
    },

    // 修改加载场景的方法
    async handleLoadScene(event) {
      try {
        const file = event.target.files[0];
        if (!file) return;

        const reader = new FileReader();
        reader.onload = async (e) => {
          try {
            const sceneData = JSON.parse(e.target.result);
            // 清空标签信息
            this.modelLabels = []
            // 清除现有场景
            while (this.diyGroup.children.length) {
              const object = this.diyGroup.children[0];
              if (object.geometry) object.geometry.dispose();
              if (object.material) object.material.dispose();
              this.diyGroup.remove(object);
            }

            // 创建模型映射表
            const modelMap = new Map();

            // 首先加载所有普通模型
            for (const modelData of sceneData.models) {
              const object = await this.createModelFromData(modelData);
              if (object) {
                this.diyGroup.add(object);
                modelMap.set(modelData.uuid, object);
                this.getOrCreateLabel(object);
              }
            }

            console.log('场景加载完成:', {
              模型数量: this.diyGroup.children.length,
            });

          } catch (error) {
            console.error('解析场景数据失败:', error);
          }
        };

        reader.readAsText(file);
      } catch (error) {
        console.error('加载场景失败:', error);
      }
    },

    // 添加从数据创建模型的辅助方法
    async createModelFromData(modelData) {
      try {
        // 根据类型创建不同的模型
        let object;

        if (modelData.type === 'tube') {
          // 创建管道模型
          const points = modelData.tubeConfig.points.map(p =>
            new THREE.Vector3(p.x, p.y, p.z)
          );

          // 确保至少有两个点来创建曲线
          if (points.length < 2) {
            points.push(points[0].clone().add(new THREE.Vector3(0, 1, 0)));
          }

          // 创建曲线
          const curve = this.createPath(points);

          // 创建管道几何体
          const geometry = new THREE.TubeGeometry(
            curve,
            modelData.tubeConfig.segments || 64,
            modelData.tubeConfig.radius || 0.1,
            modelData.tubeConfig.radialSegments || 8,
            false
          );

          // 创建材质
          const material = new THREE.MeshPhongMaterial({
            transparent: true,
            side: THREE.DoubleSide,
            color: modelData.tubeConfig.color || 0x47d8fa,
            opacity: modelData.tubeConfig.opacity || 0.8
          });

          // 创建管道网格
          object = new THREE.Mesh(geometry, material);

          // 只在启用贴图时加载流动纹理
          if (modelData.tubeConfig.useTexture) {
            new THREE.TextureLoader().load(
              require('@/static/texture/flow.png'),
              (texture) => {
                texture.wrapS = THREE.RepeatWrapping;
                texture.wrapT = THREE.RepeatWrapping;
                texture.repeat.set(points.length * 2 * Math.sign(modelData.tubeConfig.direction || 1), 1);
                material.map = texture;
                material.needsUpdate = true;
              }
            );
          }

          // 恢复管道配置
          object.userData.tubeConfig = {
            ...modelData.tubeConfig,
            points: points,
            curve: curve // 保存曲线对象以便后续更新
          };

        }
        else if (modelData.type === 'glb') {
          // 加载 GLB 模型
          const gltf = await new Promise((resolve, reject) => {
            gltfLoader.load(
              modelData.modelPath,
              resolve,
              undefined,
              reject
            );
          });

          object = gltf.scene;

          // 恢复模型属性
          object.userData = {
            isGLBModel: true,
            modelPath: modelData.modelPath,
            customFields: modelData.customFields || {}
          };

        } else if (modelData.type === 'mesh') {
          // 创建基础模型
          const geometry = new THREE.BoxGeometry(); // 或其他适当的几何体
          const material = new THREE.MeshPhongMaterial({
            color: parseInt(modelData.material.color, 16),
            opacity: modelData.material.opacity,
            transparent: modelData.material.opacity < 1
          });
          object = new THREE.Mesh(geometry, material);
        }


        if (object) {
          // 设置位置、旋转和缩放
          object.position.set(
            modelData.position.x,
            modelData.position.y,
            modelData.position.z
          );
          object.rotation.set(
            modelData.rotation.x,
            modelData.rotation.y,
            modelData.rotation.z
          );
          object.scale.set(
            modelData.scale.x,
            modelData.scale.y,
            modelData.scale.z
          );
          if (!object.userData) {
            object.userData = {};
          }
          object.userData.customFields = modelData.customFields || {}
          object.userData.name = modelData.name || ''
          object.userData.type = modelData.type || ''
          // 保存原始 UUID 用于连接
          object.uuid = modelData.uuid;
        }

        return object;
      } catch (error) {
        console.error('创建模型失败:', error);
        return null;
      }
    },
    createPath(points) {
      return new THREE.CatmullRomCurve3(points, false, 'catmullrom', 0);
    },
    // 修改创建流动管道的方法
    createFlowTube(config = {}) {
      try {
        const points = config.points || [
          new THREE.Vector3(0, 0.1, 0),
          new THREE.Vector3(0, 0.1, 2),
          new THREE.Vector3(0, 2, 2),
        ];

        const curve = this.createPath(points);

        console.log('curve', curve)

        const geometry = new THREE.TubeGeometry(
          curve,
          config.segments || 64,
          config.radius || 0.1,
          config.radialSegments || 8,
          false
        );

        const material = new THREE.MeshPhongMaterial({
          transparent: true,
          side: THREE.DoubleSide,
          color: config.color || 0x47d8fa,
          opacity: config.opacity || 0.8
        });

        const mesh = new THREE.Mesh(geometry, material);

        // 只在启用贴图时加载和应用贴图
        if (config.useTexture) {
          new THREE.TextureLoader().load(
            require('@/static/texture/flow.png'),
            (texture) => {
              texture.wrapS = THREE.RepeatWrapping;
              texture.wrapT = THREE.RepeatWrapping;
              texture.repeat.set(points.length * 2 * Math.sign(config.direction || 1), 1);
              material.map = texture;
              material.needsUpdate = true;
            }
          );
        }

        return mesh;
      } catch (error) {
        console.error('创建管道时出错:', error);
        return null;
      }
    },
    // 更新管道配置的方法
    updateTubeConfig(newConfig) {
      if (!this.selectedObject?.userData?.tubeConfig) return;

      try {
        const config = this.selectedObject.userData.tubeConfig;
        Object.assign(config, newConfig);

        // 更新几何体
        if (newConfig.points || newConfig.radius) {
          const curve = this.createPath(config.points);
          const geometry = new THREE.TubeGeometry(
            curve,
            config.segments,
            config.radius,
            config.radialSegments,
            false
          );
          this.selectedObject.geometry.dispose();
          this.selectedObject.geometry = geometry;
        }

        // 处理贴图开关
        if (newConfig.hasOwnProperty('useTexture')) {
          if (newConfig.useTexture) {
            // 启用贴图
            new THREE.TextureLoader().load(
              require('@/static/texture/flow.png'),
              (texture) => {
                texture.wrapS = THREE.RepeatWrapping;
                texture.wrapT = THREE.RepeatWrapping;
                texture.repeat.set(config.points.length * 2 * Math.sign(config.direction || 1), 1);
                this.selectedObject.material.map = texture;
                this.selectedObject.material.needsUpdate = true;
              }
            );
          } else {
            // 禁用贴图
            if (this.selectedObject.material.map) {
              this.selectedObject.material.map.dispose();
              this.selectedObject.material.map = null;
              this.selectedObject.material.needsUpdate = true;
            }
          }
        }

        // 更新材质
        if (newConfig.color !== undefined) {
          this.selectedObject.material.color.setHex(newConfig.color);
        }
        if (newConfig.opacity !== undefined) {
          this.selectedObject.material.opacity = newConfig.opacity;
        }

        // 更新流动方向
        if (newConfig.direction !== undefined && this.selectedObject.material.map) {
          this.selectedObject.material.map.repeat.x =
            Math.abs(this.selectedObject.material.map.repeat.x) * Math.sign(newConfig.direction);
          this.selectedObject.material.map.needsUpdate = true;
        }

        this.selectedObject.material.needsUpdate = true;
      } catch (error) {
        console.error('更新管道配置时出错:', error);
      }
    },
    // 添加获取相交对象的辅助方法
    getIntersects(event) {
      const rect = this.renderer.domElement.getBoundingClientRect();
      const x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
      const y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

      const raycaster = new THREE.Raycaster();
      raycaster.setFromCamera(new THREE.Vector2(x, y), this.camera);

      // 只检测 diyGroup 中的对象
      return raycaster.intersectObjects(this.diyGroup.children, true);
    },

    // 修改场景点击事件处理
    onSceneClick(event) {
      const intersects = this.getIntersects(event);
      if (intersects.length > 0) {
        const clickedObject = intersects[0].object;
        // 如果点击的是 GLB 模型的一部分，找到其根节点（整个模型）
        if (clickedObject.parent) {
          let rootObject = clickedObject;
          while (rootObject.parent && rootObject.parent !== this.diyGroup) {
            rootObject = rootObject.parent;
          }
          this.selectObject(rootObject);
        } else {
          this.selectObject(clickedObject);
        }
      } else {
        this.selectObject(null);
      }
    },



    // 添加新的自定义字段
    addCustomField() {
      const newKey = `field_${Object.keys(this.objectProps.customFields).length}`;
      this.$set(this.objectProps.customFields, newKey, '');
      this.$set(this.customFieldKeys, newKey, '');

      if (this.selectedObject) {
        if (!this.selectedObject.userData.customFields) {
          this.selectedObject.userData.customFields = {};
        }
        this.selectedObject.userData.customFields[newKey] = '';
      }
    },

    // 修改更新字段名的方法
    updateCustomFieldKey(oldKey, newKey) {
      // 如果新键为空或者与旧键相同，不做处理
      if (!newKey || newKey === oldKey) {
        return;
      }

      // 如果新键已存在，也不做处理
      if (this.objectProps.customFields.hasOwnProperty(newKey)) {
        return;
      }

      try {
        const value = this.objectProps.customFields[oldKey];

        // 使用 Vue.set 来确保响应性
        this.$set(this.objectProps.customFields, newKey, value);
        this.$set(this.customFieldKeys, newKey, newKey);

        // 删除旧的键
        this.$delete(this.objectProps.customFields, oldKey);
        this.$delete(this.customFieldKeys, oldKey);

        // 更新对象的 userData
        if (this.selectedObject?.userData.customFields) {
          const objValue = this.selectedObject.userData.customFields[oldKey];
          this.selectedObject.userData.customFields[newKey] = objValue;
          delete this.selectedObject.userData.customFields[oldKey];
        }
      } catch (error) {
        console.error('更新字段名时出错:', error);
      }
    },

    // 添加一个新的方法来处理输入事件
    handleFieldKeyInput(event, oldKey) {
      const newKey = event.target.value;
      // 只更新临时存储的键名，不立即更新实际的字段名
      this.$set(this.customFieldKeys, oldKey, newKey);
    },

    // 添加一个方法来处理失焦事件
    handleFieldKeyBlur(oldKey) {
      const newKey = this.customFieldKeys[oldKey];
      // 在失焦时才真正更新字段名
      this.updateCustomFieldKey(oldKey, newKey);
    },

    // 更新字段值
    updateCustomField(key, value) {
      if (this.selectedObject?.userData.customFields) {
        this.selectedObject.userData.customFields[key] = value;
      }
    },

    // 删除字段
    removeCustomField(key) {
      this.$delete(this.objectProps.customFields, key);
      this.$delete(this.customFieldKeys, key);

      if (this.selectedObject?.userData.customFields) {
        delete this.selectedObject.userData.customFields[key];
      }
    },

    // 添加输入框焦点控制方法
    handleInputFocus() {
      if (this.controls) {
        this.controls.enabled = false;
      }
    },

    handleInputBlur() {
      if (this.controls) {
        this.controls.enabled = true;
      }
    },

    // 更新标签位置
    updateLabelsPosition() {
      if (!this.showLabels) return; // 如果标签被隐藏，不更新位置
      this.modelLabels.forEach(label => {
        if (label.object && label.object.userData.showLabel) {
          // 计算包围盒
          const boundingBox = new THREE.Box3().setFromObject(label.object);
          const height = boundingBox.max.y - boundingBox.min.y;

          // 获取模型在屏幕上的位置
          const vector = new THREE.Vector3();
          // 设置位置为模型的顶部中心点
          vector.set(
            label.object.position.x,
            label.object.position.y + height + 0.2, // 提高标签位置
            label.object.position.z
          );

          // 将世界坐标转换为屏幕坐标
          vector.project(this.camera);

          // 转换为像素坐标
          const x = (vector.x * 0.5 + 0.5) * this.$refs.container.clientWidth;
          const y = (-vector.y * 0.5 + 0.5) * this.$refs.container.clientHeight;

          // 更新标签位置
          label.style = {
            transform: `translate(-50%, -100%) translate(${x}px, ${y}px)`,
            display: vector.z > 1 ? 'none' : 'block',
            zIndex: Math.floor((1 - vector.z) * 1000), // 前面标签 zIndex 高于后面标签
          };

          // 根据到相机的距离设置可见性
          label.visible = vector.z <= 1;
        }
      });
    },

    // 处理开关状态变化
    handleSwitchChange(label) {
      console.log('开关状态改变:', label.title, label.switchState);
      // 这里可以添加其他需要的处理逻辑
    },

    // 添加模型预加载方法
    preloadModels() {
      this.modelGroups.forEach(group => {
        group.models.forEach(model => {
          if (model.type === 'glb') {
            // 预加载GLB模型
            gltfLoader.load(model.path, (gltf) => {
              // 可以在这里缓存模型或处理预加载完成的回调
              console.log(`模型 ${model.name} 预加载完成`)
            })
          }
        })
      })
    },
    // 添加路径点
    addPathPoint() {
      if (!this.selectedObject?.userData?.tubeConfig) return;

      const points = this.objectProps.tubeConfig.points;
      const lastPoint = points[points.length - 1];

      // 根据最后一个点创建新点，稍微偏移一点位置
      const newPoint = new THREE.Vector3(
        lastPoint.x,
        lastPoint.y + 1, // 向上偏移1个单位
        lastPoint.z
      );

      points.push(newPoint);
      this.updateTubePath();
    },

    // 删除路径点
    removePathPoint(index) {
      if (!this.selectedObject?.userData?.tubeConfig) return;

      const points = this.objectProps.tubeConfig.points;
      if (points.length <= 2) return; // 保持至少2个点

      points.splice(index, 1);
      this.updateTubePath();
    },

    // 更新管道路径
    updateTubePath() {
      if (!this.selectedObject?.userData?.tubeConfig) return;

      try {
        const points = this.objectProps.tubeConfig.points;
        const curve = this.createPath(points);

        // 创建新的管道几何体
        const geometry = new THREE.TubeGeometry(
          curve,
          this.selectedObject.userData.tubeConfig.segments || 64,
          this.selectedObject.userData.tubeConfig.radius || 0.1,
          this.selectedObject.userData.tubeConfig.radialSegments || 8,
          false
        );

        // 更新几何体
        this.selectedObject.geometry.dispose();
        this.selectedObject.geometry = geometry;

        // 更新 userData 中的路径数据
        this.selectedObject.userData.tubeConfig.points = points.map(p => p.clone());
        this.selectedObject.userData.tubeConfig.curve = curve;

        // 更新流动纹理
        if (this.selectedObject.material.map) {
          this.selectedObject.material.map.repeat.set(
            points.length * 2 * Math.sign(this.selectedObject.userData.tubeConfig.direction || 1),
            1
          );
          this.selectedObject.material.map.needsUpdate = true;
        }
      } catch (error) {
        console.error('更新管道路径时出错:', error);
      }
    },
    deleteSelectedObject() {
      if (!this.selectedObject) return;

      try {

        // 清理材质和几何体
        if (this.selectedObject.material) {
          if (this.selectedObject.material.map) {
            this.selectedObject.material.map.dispose();
          }
          this.selectedObject.material.dispose();
        }
        if (this.selectedObject.geometry) {
          this.selectedObject.geometry.dispose();
        }

        // 从场景中移除
        this.diyGroup.remove(this.selectedObject);

        // 清空选中状态
        this.selectedObject = null;
        this.objectProps = {};
        this.selectObject(null)

        this.renderer.render(this.scene, this.camera);


      } catch (error) {
        console.error('删除模型时出错:', error);
      }
    }
  },

  beforeUnmount() {
    window.removeEventListener('resize', this.onWindowResize);
    if (this.renderer && this.renderer.domElement) {
      this.renderer.dispose();
      this.renderer.domElement.remove();
    }
    if (this.controls) {
      this.controls.dispose();
    }
    if (this.transformControls) {
      this.transformControls.dispose();
    }
    if (this.scene) {
      this.disposeScene(this.scene);
    }
    if (this.renderer && this.renderer.domElement) {
      this.renderer.domElement.removeEventListener('click', this.onSceneClick);
    }
  },
}
</script>

<style scoped>
.editor-container {
  display: flex;
  height: 100vh;
  overflow: hidden;
}

.model-sidebar {
  width: 250px;
  border-right: 1px solid #ddd;
  overflow-y: auto;
  padding: 16px;
}

.scene-container {
  flex: 1;
  position: relative;
}

.property-panel {
  width: 360px;
  border-left: 1px solid #ddd;
  padding: 16px;
  overflow-y: auto;
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  background: #ffffff;
  z-index: 9999;
}

.property-panel .tabs {
  display: flex;
}

.property-panel .tabs .tabs-item {
  flex: 1;
  text-align: center;
  font-size: 18px;
  padding: 10px 0;
  border-bottom: 4px solid transparent;
  cursor: pointer;
  user-select: none;
}

.property-panel .tabs .tabs-item.active {
  border-color: #1890ff;
  color: #1890ff;
}

.model-group {
  margin-bottom: 16px;
}

.group-header {
  padding: 8px;
  background: #f5f5f5;
  cursor: pointer;
  display: flex;
  align-items: center;
  border-radius: 4px;
}

.model-item {
  padding: 8px;
  margin: 4px 0;
  border: 1px solid #ddd;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  transition: background-color 0.2s;
}

.model-item:hover {
  background-color: #f0f0f0;
}

.toolbar {
  position: absolute;
  top: 16px;
  left: 16px;
  background: white;
  padding: 8px;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.toolbar button {
  margin-right: 8px;
  padding: 4px 12px;
  border: none;
  background: #1890ff;
  color: white;
  border-radius: 4px;
  cursor: pointer;
}

.toolbar button:hover {
  background: #40a9ff;
}

.property-group {
  margin-bottom: 24px;
}

.property-group h3 {
  margin-bottom: 12px;
  color: #333;
}

.property-row {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
}

.label {
  width: 80px;
  color: #666;
}

.property-row input {
  flex: 1;
  padding: 4px 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

input[type="color"] {
  width: 100%;
  height: 32px;
  padding: 2px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.label-title {
  font-size: 14px;
  font-weight: 500;
}

/* Switch 开关样式 */
.switch {
  position: relative;
  display: inline-block;
  width: 40px;
  height: 20px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ccc;
  transition: .4s;
  border-radius: 20px;
}

.slider:before {
  position: absolute;
  content: "";
  height: 16px;
  width: 16px;
  left: 2px;
  bottom: 2px;
  background-color: white;
  transition: .4s;
  border-radius: 50%;
}

input:checked+.slider {
  background-color: #1890ff;
}

input:checked+.slider:before {
  transform: translateX(20px);
}

/* 调整标签样式 */
.model-label {
  position: absolute;
  padding: 12px;
  border-radius: 6px;
  background-color: rgba(26, 57, 88, 0.55);
  min-width: 130px;
  box-shadow: 0 2px 12px rgba(70, 158, 193, 0.5), 0 2px 8px rgba(70, 158, 193, 0.5) inset;
  pointer-events: auto;
  backdrop-filter: blur(4px);
}

.model-label::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  border-radius: 6px;
  border: 2px solid rgba(70, 158, 193, 0.9);
  clip-path: polygon(0 0, 100% 0, 100% 100%, calc(50% + 7px) 100%, 50% calc(100% - 5px), calc(50% - 7px) 100%, 0 100%, 0 0);
}

.model-label::after {
  content: "";
  position: absolute;
  bottom: -4px;
  left: calc(50% - 5px);
  width: 10px;
  height: 10px;
  transform: rotate(-45deg);
  border: 2px solid rgba(70, 158, 193, 0.9);
  background-color: rgba(26, 57, 88, 0.55);
  clip-path: polygon(0 0, 0 100%, 100% 100%);
}

.label-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(26, 57, 88, 0.55);
  color: #fff;
}

.label-content {
  font-size: 13px;
  color: #fff;
}

.label-field {
  margin-bottom: 6px;
  display: flex;
  justify-content: space-between;
}

.label-field:last-child {
  margin-bottom: 0;
}

.loading-tip {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(0, 0, 0, 0.7);
  color: white;
  padding: 10px 20px;
  border-radius: 4px;
  z-index: 1000;
}

.path-editor {
  margin-top: 16px;
  border-top: 1px solid #eee;
  padding-top: 16px;
}

.path-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.path-header h4 {
  margin: 0;
  color: #333;
}

.add-point-btn {
  padding: 4px 12px;
  background: #1890ff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.add-point-btn:hover {
  background: #40a9ff;
}

.path-point {
  background: #f5f5f5;
  border-radius: 4px;
  padding: 8px;
  margin-bottom: 8px;
}

.point-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.remove-point-btn {
  padding: 2px 8px;
  background: #ff4d4f;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.remove-point-btn:disabled {
  background: #d9d9d9;
  cursor: not-allowed;
}

.remove-point-btn:hover:not(:disabled) {
  background: #ff7875;
}

.point-coords {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

.coord-input {
  display: flex;
  align-items: center;
}

.coord-input label {
  width: 20px;
  margin-right: 4px;
}

.coord-input input {
  width: 100%;
  padding: 4px;
  border: 1px solid #d9d9d9;
  border-radius: 2px;
}

.panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.panel-header h2 {
  margin: 0;
}

.delete-btn {
  background-color: #ff4d4f;
  color: white;
  border: none;
  padding: 6px 12px;
  border-radius: 4px;
  cursor: pointer;
}
</style>